home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / X11GRAPH.C < prev    next >
C/C++ Source or Header  |  1992-01-31  |  38KB  |  1,060 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d polygonal solid modeller.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber            Unix - X11 Ver 0.1, Mar. 1990    *
  5. ******************************************************************************
  6. *   General routines to    handle the graphic calls.                 *
  7. * currently supported devices:                             *
  8. * Input: Keyboard, mouse.                             *
  9. * Output: X11 device.                                 *
  10. *****************************************************************************/
  11.  
  12. #ifdef __hpux
  13. typedef char *caddr_t;        /* Awful kluge. Let me know of a better way. */
  14. #endif /* __hpux */
  15.  
  16. #include <X11/Xlib.h>
  17. #include <X11/Xutil.h>
  18. #include <X11/cursorfont.h>
  19. #include <X11/Xresource.h>
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <math.h>
  24. #include <ctype.h>
  25. #include "graphgen.h"
  26.  
  27. #define    POINT_SIZE 0.05                  /* Size of + marker drawn. */
  28. #define    POINT_TITLE 0.02       /* Distance between point title and + marker. */
  29.  
  30. #define FONT_NAME        "8x13"
  31. #define PROGRAM_NAME        "irit"
  32. #define DEFAULT_TRANS_WIDTH    200
  33. #define DEFAULT_TRANS_HEIGHT    500
  34. #define DEFAULT_VIEW_WIDTH    400
  35. #define DEFAULT_VIEW_HEIGHT    400
  36.  
  37. /* X global specific staff goes here: */
  38. static Display *XDisplay;
  39. static int XScreen;
  40. static Window XRoot;
  41. static Colormap XColorMap;
  42. static GC XTransGraphContext;
  43. static GC XViewGraphContext;
  44. static Visual *XVisual;
  45. static XImage *XImageBuffer;
  46. static Pixmap XIcon;
  47. static Cursor XCursor;
  48. static XColor BlackColor;
  49. static XFontStruct *XLoadedFont;
  50. static XColor
  51.     *TransCursorColor = NULL,
  52.     *ViewCursorColor = NULL;
  53. static unsigned long
  54.     TransBackGroundPixel,
  55.     TransBorderPixel,
  56.     TransTextPixel,
  57.     TransSubWinBackPixel,
  58.     TransSubWinBorderPixel,
  59.     ViewBackGroundPixel,
  60.     ViewBorderPixel,
  61.     ViewTextPixel;
  62. static int
  63.     XFontYOffsetToCenter = 0,
  64.     AbortKeyPressed = FALSE,
  65.     TransHasSize = FALSE,
  66.     TransHasPos = FALSE,
  67.     TransPosX = 0,
  68.     TransPosY = 0,
  69.     ViewHasSize = FALSE,
  70.     ViewHasPos = FALSE,
  71.     ViewPosX = 0,
  72.     ViewPosY = 0,
  73.     CurrentXPosition = 0,
  74.     CurrentYPosition = 0,
  75.     PopTransWndwAlways = TRUE,
  76.     LclFullTransMode = TRUE,
  77.     InGraphicMode = FALSE;
  78. static unsigned int
  79.     TransBorderWidth = 1,
  80.     TransSubWinBorderWidth = 1,
  81.     TransWidth = DEFAULT_TRANS_WIDTH,
  82.     TransHeight = DEFAULT_TRANS_HEIGHT,
  83.     ViewBorderWidth = 1,
  84.     ViewWidth = DEFAULT_VIEW_WIDTH,
  85.     ViewHeight = DEFAULT_VIEW_HEIGHT;
  86.  
  87. /* X Colors to be used for viewed object (see also xgraphic.h): */
  88. int XViewColorDefs[MAX_COLOR + 1][3] =
  89. {
  90.     {     0,     0,     0 },  /* 0. BLACK */
  91.     {     0,     0, 43350 },  /* 1. BLUE */
  92.     {     0, 43350,     0 },  /* 2. GREEN */
  93.     {     0, 43350, 43350 },  /* 3. CYAN */
  94.     { 43350,     0,     0 },  /* 4. RED */
  95.     { 43350,     0, 43350 },  /* 5. MAGENTA */
  96.     { 43350, 43350,     0 },  /* 6. BROWN */
  97.     { 43350, 43350, 43350 },  /* 7. LIGHTGREY */
  98.     { 21675, 21675, 21675 },  /* 8. DARKGRAY */
  99.     { 21675, 21675, 65535 },  /* 9. LIGHTBLUE */
  100.     { 21675, 65535, 21675 },  /* 10. LIGHTGREEN */
  101.     { 21675, 65535, 65535 },  /* 11. LIGHTCYAN */
  102.     { 65535, 21675, 21675 },  /* 12. LIGHTRED */
  103.     { 65535, 21675, 65535 },  /* 13. LIGHTMAGENTA */
  104.     { 65535, 65535, 21675 },  /* 14. YELLOW */
  105.     { 65535, 65535, 65535 }   /* 15. WHITE */
  106. };
  107. XColor XViewColors[MAX_COLOR + 1];
  108.  
  109. /* X Viewing window staff goes here: */
  110. static Window ViewWndw;
  111.  
  112. /* X transformation window staff goes here: */
  113. static Window TransformWndw;
  114. static Window ObjScrTglWndw;
  115. static Window PersOrthoTglWndw, PersOrthoZWndw;
  116. static Window RotateXWndw, RotateYWndw, RotateZWndw;
  117. static Window TranslateXWndw, TranslateYWndw, TranslateZWndw;
  118. static Window ScaleWndw;
  119. static Window DepthCueWndw;
  120. static Window SaveGIFWndw;
  121. static Window SavePSWndw;
  122. static Window SaveMatrixWndw;
  123. static Window ResetMatrixWndw;
  124. static Window QuitWndw;
  125.  
  126. /* Viewing state variables: */
  127. static int
  128.     ObjectSpaceState = FALSE,
  129.     PerspectiveState = FALSE,
  130.     DepthCueState = FALSE,
  131.     SubWindowWidthState2 = 1,
  132.     SubWindowHeightState2 = 1;
  133.  
  134. static int GGMapX(RealType x);
  135. static int GGMapY(RealType y);
  136. static void ReadXDefaults(void);
  137. static char *ReadOneXDefault(char *Entry);
  138. static void SetTransformWindow(int argc, char **argv);
  139. static void RedrawTransformWindow(void);
  140. static Window SetTransformSubWindow(int SubTransPosX, int SubTransPosY,
  141.             unsigned int SubTransWidth, unsigned int SubTransHeight);
  142. static void RedrawTransformSubWindow(Window Win,
  143.     int SubTransPosX, int SubTransPosY,
  144.     unsigned int SubTransWidth, unsigned int SubTransHeight,
  145.     int DrawMiddleVertLine, char *DrawString);
  146. static void SetViewWindow(int argc, char **argv);
  147. static void DrawText(Window Win, char *Str, int PosX, int PosY,
  148.              unsigned long Color);
  149.  
  150. /****************************************************************************
  151. * Routine to map real -1..1 normalized coordinates to screen X size.        *
  152. ****************************************************************************/
  153. static int GGMapX(RealType x)
  154. {
  155.     return ((int) ((x + 1.0) * ViewWidth)) / 2;
  156. }
  157.  
  158. /****************************************************************************
  159. * Routine to map real -1..1 normalized coordinates to screen Y size.        *
  160. ****************************************************************************/
  161. static int GGMapY(RealType y)
  162. {
  163.     return ((int) ((1.0 - y) * ViewHeight)) / 2;
  164. }
  165.  
  166. /****************************************************************************
  167. * Routine to move to a normalized point    between    -1..1 on both axes :        *
  168. ****************************************************************************/
  169. void GGMyMove(RealType x, RealType y)
  170. {
  171.     CurrentXPosition = GGMapX(x);
  172.     CurrentYPosition = GGMapY(y);
  173. }
  174.  
  175. /****************************************************************************
  176. * Routine to draw to a normalized point    between    -1..1 on both axes :        *
  177. ****************************************************************************/
  178. void GGMyDraw(RealType x, RealType y)
  179. {
  180.     int NewX, NewY;
  181.  
  182.     XDrawLine(XDisplay, ViewWndw, XViewGraphContext,
  183.           CurrentXPosition, CurrentYPosition,
  184.           NewX = GGMapX(x), NewY = GGMapY(y));
  185.  
  186.     CurrentXPosition = NewX;
  187.     CurrentYPosition = NewY;
  188. }
  189.  
  190. /****************************************************************************
  191. * Routine to set line style.                            *
  192. ****************************************************************************/
  193. void GGMySetLineStyle(int Style)
  194. {
  195.     switch (Style) {
  196.     case SOLID_LINE:
  197.         XSetLineAttributes(XDisplay, XViewGraphContext,
  198.                    0, LineSolid, CapRound, JoinRound);
  199.         break;
  200.     case DOTTED_LINE:
  201.         XSetLineAttributes(XDisplay, XViewGraphContext,
  202.                    0, LineOnOffDash, CapRound, JoinRound);
  203.         break;
  204.     }
  205. }
  206.  
  207. /****************************************************************************
  208. * Routine to draw to a normelized point    between    -1..1 on both axes :        *
  209. ****************************************************************************/
  210. void GGMySetColor(int color)
  211. {
  212.     XGCValues values;
  213.  
  214.     if (color > MAX_COLOR) color = WHITE;
  215.  
  216.     values.foreground = XViewColors[color].pixel;
  217.     XChangeGC(XDisplay, XViewGraphContext, GCForeground, &values);
  218. }
  219.  
  220. /****************************************************************************
  221. * Routine to reset all the system to starting condition    :            *
  222. ****************************************************************************/
  223. void GGInitGraph(int argc, char **argv, int FullTransMode, int TransAlways)
  224. {
  225.     int i;
  226.     XGCValues values;
  227.  
  228.     LclFullTransMode = FullTransMode;
  229.  
  230.     PopTransWndwAlways = TransAlways;
  231.  
  232.     /* Lets see if we can get access to the X server before we even start: */
  233.     if ((XDisplay = (Display *) XOpenDisplay(NULL)) == NULL) {
  234.     fprintf(stderr, "Failed to access X server, abored.\n");
  235.         MyExit(-1);
  236.     }
  237.     if ((XLoadedFont = XLoadQueryFont(XDisplay, FONT_NAME)) == NULL) {
  238.     fprintf(stderr, "Failed to load required X font \"%s\", aborted.\n",
  239.         FONT_NAME);
  240.     MyExit(-1);
  241.     }
  242.     XFontYOffsetToCenter = (XLoadedFont -> ascent - XLoadedFont -> descent + 1)
  243.                                     / 2;
  244.  
  245.     XScreen = DefaultScreen(XDisplay);
  246.     XRoot = RootWindow(XDisplay, XScreen);
  247.     XColorMap = DefaultColormap(XDisplay, XScreen);
  248.     XVisual = DefaultVisual(XDisplay, XScreen);
  249.     values.foreground = WhitePixel(XDisplay, XScreen);
  250.     values.background = BlackPixel(XDisplay, XScreen);
  251.     values.font = XLoadedFont -> fid;
  252.     XTransGraphContext = XCreateGC(XDisplay, XRoot,
  253.                   GCForeground | GCBackground | GCFont, &values);
  254.     XViewGraphContext = XCreateGC(XDisplay, XRoot,
  255.                   GCForeground | GCBackground, &values);
  256.     
  257.     if (XDisplay->db == NULL)
  258.     XGetDefault(XDisplay, "", "");
  259.     ReadXDefaults();
  260.  
  261.     for (i = 0; i <= MAX_COLOR; i++) {
  262.     XViewColors[i].red   = XViewColorDefs[i][0];
  263.     XViewColors[i].green = XViewColorDefs[i][1];
  264.     XViewColors[i].blue  = XViewColorDefs[i][2];
  265.  
  266.     /* If fails to allocate the color - take WHITE instead. */
  267.     if (!XAllocColor(XDisplay, XColorMap, &XViewColors[i]))
  268.         XViewColors[i].pixel = WhitePixel(XDisplay, XScreen);
  269.     }
  270.  
  271.     SetTransformWindow(argc, argv);
  272.     SetViewWindow(argc, argv);
  273.  
  274.     GGGraphicFlush();
  275.  
  276.     InGraphicMode = TRUE;
  277. }
  278.  
  279. /****************************************************************************
  280. * Routine to close and shutdown    graphic    mode :                    *
  281. ****************************************************************************/
  282. void GGCloseGraph(void)
  283. {
  284.     if (!InGraphicMode) return;
  285.  
  286.     XFreeGC(XDisplay, XViewGraphContext);
  287.     XFreeGC(XDisplay, XTransGraphContext);
  288.     XUnloadFont(XDisplay, XLoadedFont -> fid);
  289.     XCloseDisplay(XDisplay);
  290.  
  291.     InGraphicMode = FALSE;
  292. }
  293.  
  294. /*****************************************************************************
  295. * Routine to print an message on the given location:                 *
  296. *****************************************************************************/
  297. void GGPutMsgXY(char *s, RealType x, RealType y)
  298. {
  299.     int Len = strlen(s),
  300.         Width = XTextWidth(XLoadedFont, s, Len),
  301.         PosX = GGMapX(x),
  302.         PosY = GGMapY(y);
  303.     XGCValues values;
  304.  
  305.     XDrawString(XDisplay, ViewWndw, XViewGraphContext, PosX - Width / 2,
  306.         PosY + XFontYOffsetToCenter, s, Len);
  307. }
  308.  
  309. /*****************************************************************************
  310. *   Routine to clear the vewing area.                         *
  311. *****************************************************************************/
  312. void GGClearViewArea(void)
  313. {
  314.     XClearWindow(XDisplay, ViewWndw);
  315. }
  316.  
  317. /*****************************************************************************
  318. * Routine to make some sound with given Frequency, Time milliseconds:         *
  319. *****************************************************************************/
  320. void GGTone(int Frequency, int Duration)
  321. {
  322.     if (GlblDoGraphics)
  323.     XBell(XDisplay, 0);
  324. }
  325.  
  326. /*****************************************************************************
  327. * Read one default from X resource data base.                     *
  328. *****************************************************************************/
  329. static char *ReadOneXDefault(char *Entry)
  330. {
  331.     XrmString Type;
  332.     XrmValue Result;
  333.     char Line[LINE_LEN_LONG];
  334.  
  335.     sprintf(Line, "%s.%s", PROGRAM_NAME, Entry);
  336.     if ( XrmGetResource(XDisplay->db, Line, "Program.Name", &Type, &Result ) )
  337.     return Result.addr;
  338.     else
  339.     return NULL;
  340. }
  341.  
  342. /*****************************************************************************
  343. * Read Defaults from X data base.                         *
  344. *****************************************************************************/
  345. static void ReadXDefaults(void)
  346. {
  347.     int i;
  348.     XColor Color;
  349.     char *TransBackGroundColor = ReadOneXDefault("Trans.BackGround"),
  350.          *TransBorderColor = ReadOneXDefault("Trans*BorderColor"),
  351.          *TransBorderWidthStr = ReadOneXDefault("Trans*BorderWidth"),
  352.          *TransTextColor = ReadOneXDefault("Trans.TextColor"),
  353.          *TransSubWinBackColor = ReadOneXDefault("Trans.SubWin.BackGround"),
  354.          *TransSubWinBorderColor = ReadOneXDefault("Trans.SubWin.BorderColor"),
  355.          *TransSubWinBorderWidthStr = ReadOneXDefault("Trans.SubWin.BorderWidth"),
  356.          *TransGeometry = ReadOneXDefault("Trans.Geometry"),
  357.          *TransCursorColorStr = ReadOneXDefault("Trans.CursorColor"),
  358.          *ViewBackGroundColor = ReadOneXDefault("View.BackGround"),
  359.          *ViewTextColor = ReadOneXDefault("View.TextColor"),
  360.          *ViewBorderColor = ReadOneXDefault("View.BorderColor"),
  361.          *ViewBorderWidthStr = ReadOneXDefault("View.BorderWidth"),
  362.          *ViewGeometry = ReadOneXDefault("View.Geometry"),
  363.          *ViewCursorColorStr = ReadOneXDefault("View.CursorColor");
  364.  
  365.     if (XParseColor(XDisplay, XColorMap, "Black", &BlackColor))
  366.     XAllocColor(XDisplay, XColorMap, &BlackColor);
  367.  
  368.     if (TransBackGroundColor != NULL &&
  369.     XParseColor(XDisplay, XColorMap, TransBackGroundColor, &Color) &&
  370.     XAllocColor(XDisplay, XColorMap, &Color))
  371.     TransBackGroundPixel = Color.pixel;
  372.     else
  373.     TransBackGroundPixel = BlackPixel(XDisplay, XScreen);
  374.  
  375.     if (TransBorderColor != NULL &&
  376.     XParseColor(XDisplay, XColorMap, TransBorderColor, &Color) &&
  377.     XAllocColor(XDisplay, XColorMap, &Color))
  378.     TransBorderPixel = Color.pixel;
  379.     else
  380.     TransBorderPixel = WhitePixel(XDisplay, XScreen);
  381.  
  382.     if (TransBorderWidthStr)
  383.     TransBorderWidth = atoi(TransBorderWidthStr);
  384.     else
  385.     TransBorderWidth = 1;
  386.  
  387.     if (TransTextColor != NULL &&
  388.     XParseColor(XDisplay, XColorMap, TransTextColor, &Color) &&
  389.     XAllocColor(XDisplay, XColorMap, &Color))
  390.     TransTextPixel = Color.pixel;
  391.     else
  392.     TransTextPixel = WhitePixel(XDisplay, XScreen);
  393.  
  394.     if (TransSubWinBackColor != NULL &&
  395.     XParseColor(XDisplay, XColorMap, TransSubWinBackColor, &Color) &&
  396.     XAllocColor(XDisplay, XColorMap, &Color))
  397.     TransSubWinBackPixel = Color.pixel;
  398.     else
  399.     TransSubWinBackPixel = BlackPixel(XDisplay, XScreen);
  400.  
  401.     if (TransSubWinBorderColor != NULL &&
  402.     XParseColor(XDisplay, XColorMap, TransSubWinBorderColor, &Color) &&
  403.     XAllocColor(XDisplay, XColorMap, &Color))
  404.     TransSubWinBorderPixel = Color.pixel;
  405.     else
  406.     TransSubWinBorderPixel = WhitePixel(XDisplay, XScreen);
  407.  
  408.     if (TransSubWinBorderWidthStr)
  409.     TransSubWinBorderWidth = atoi(TransSubWinBorderWidthStr);
  410.     else
  411.     TransSubWinBorderWidth = 1;
  412.  
  413.     if (TransGeometry) {
  414.     i = XParseGeometry(TransGeometry, &TransPosX, &TransPosY,
  415.                                   &TransWidth, &TransHeight);
  416.     TransHasPos = i & XValue && i & YValue;
  417.     TransHasSize =  i & WidthValue && i & HeightValue;
  418.     }
  419.     else
  420.         TransHasSize = TransHasPos = FALSE;
  421.  
  422.     if (TransCursorColorStr != NULL &&
  423.     XParseColor(XDisplay, XColorMap, TransCursorColorStr, &Color) &&
  424.     XAllocColor(XDisplay, XColorMap, &Color)) {
  425.     TransCursorColor = (XColor *) malloc(sizeof(XColor));
  426.     *TransCursorColor = Color;
  427.     }
  428.     else
  429.     TransCursorColor = NULL;
  430.  
  431.     if (ViewBackGroundColor &&
  432.     XParseColor(XDisplay, XColorMap, ViewBackGroundColor, &Color) &&
  433.     XAllocColor(XDisplay, XColorMap, &Color))
  434.     ViewBackGroundPixel = Color.pixel;
  435.     else
  436.     ViewBackGroundPixel = BlackPixel(XDisplay, XScreen);
  437.  
  438.     if (ViewBorderColor &&
  439.     XParseColor(XDisplay, XColorMap, ViewBorderColor, &Color) &&
  440.     XAllocColor(XDisplay, XColorMap, &Color))
  441.     ViewBorderPixel = Color.pixel;
  442.     else
  443.     ViewBorderPixel = WhitePixel(XDisplay, XScreen);
  444.  
  445.     if (ViewTextColor != NULL &&
  446.     XParseColor(XDisplay, XColorMap, ViewTextColor, &Color) &&
  447.     XAllocColor(XDisplay, XColorMap, &Color))
  448.     ViewTextPixel = Color.pixel;
  449.     else
  450.     ViewTextPixel = WhitePixel(XDisplay, XScreen);
  451.  
  452.     if (ViewBorderWidthStr)
  453.     ViewBorderWidth = atoi(ViewBorderWidthStr);
  454.     else
  455.     ViewBorderWidth = 1;
  456.  
  457.     if (ViewGeometry) {
  458.     i = XParseGeometry(ViewGeometry, &ViewPosX, &ViewPosY,
  459.                                  &ViewWidth, &ViewHeight);
  460.     ViewHasPos = i & XValue && i & YValue;
  461.     ViewHasSize = i & WidthValue && i & HeightValue;
  462.     }
  463.     else ViewHasSize = ViewHasPos = FALSE;
  464.  
  465.     if (ViewCursorColorStr != NULL &&
  466.     XParseColor(XDisplay, XColorMap, ViewCursorColorStr, &Color) &&
  467.     XAllocColor(XDisplay, XColorMap, &Color)) {
  468.     ViewCursorColor = (XColor *) malloc(sizeof(XColor));
  469.     *ViewCursorColor = Color;
  470.     }
  471.     else
  472.     ViewCursorColor = NULL;
  473. }
  474.  
  475. /*****************************************************************************
  476. * Set up and draw a transformation window.                     *
  477. *****************************************************************************/
  478. static void SetTransformWindow(int argc, char **argv)
  479. {
  480.     int SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight;
  481.     long ValueMask;
  482.     XSizeHints Hints;
  483.     XSetWindowAttributes SetWinAttr;
  484.  
  485.     SetWinAttr.background_pixel = TransBackGroundPixel;
  486.     SetWinAttr.border_pixel = TransBorderPixel;
  487.     ValueMask = CWBackPixel | CWBorderPixel;
  488.  
  489.     Hints.flags = PMinSize | PMaxSize;
  490.     Hints.x = Hints.y = 1;
  491.     Hints.min_width = 100;
  492.     Hints.max_width = 1000;
  493.     Hints.min_height = 200;
  494.     Hints.max_height = 1000;
  495.     if (TransHasSize) {
  496.     Hints.flags |= PSize;
  497.     if (TransWidth < Hints.min_width) TransWidth = Hints.min_width;
  498.     if (TransWidth > Hints.max_width) TransWidth = Hints.max_width;
  499.     if (TransHeight < Hints.min_height) TransHeight = Hints.min_height;
  500.     if (TransHeight > Hints.max_height) TransHeight = Hints.max_height;
  501.     Hints.width = TransWidth;
  502.     Hints.height = TransHeight;
  503.     }
  504.     else {
  505.     Hints.flags |= PSize;
  506.     Hints.width = TransWidth = DEFAULT_TRANS_WIDTH;
  507.     Hints.height = TransHeight = DEFAULT_TRANS_HEIGHT;
  508.     }
  509.     if (TransHasPos) {
  510.     Hints.flags |= USPosition;
  511.     Hints.x = TransPosX;
  512.     Hints.y = TransPosY;
  513.     }
  514.  
  515.     TransformWndw = XCreateWindow(XDisplay, XRoot,
  516.                   TransPosX, TransPosY,
  517.                   TransWidth, TransHeight,
  518.                       1, 0, CopyFromParent, CopyFromParent,
  519.                       ValueMask, &SetWinAttr);
  520.  
  521.     XSetStandardProperties(XDisplay, TransformWndw,
  522.                PROGRAM_NAME, PROGRAM_NAME, None,
  523.                argv, argc,
  524.                &Hints);
  525.  
  526.     /* Set our own cursor: */
  527.     XCursor = XCreateFontCursor(XDisplay, XC_hand1);
  528.     XDefineCursor(XDisplay, TransformWndw, XCursor);
  529.     if (TransCursorColor != NULL)
  530.     XRecolorCursor(XDisplay, XCursor, TransCursorColor, &BlackColor);
  531.  
  532.     /* Now lets create the sub windows inside. Note we do not place them yet. */
  533.     SubTransPosX = 0;
  534.     SubTransPosY = TransHeight;
  535.     SubTransWidth = TransWidth - SubTransPosX * 2;
  536.     SubTransHeight = TransHeight / 25;
  537.  
  538.     /* OBJECT/SCREEN space toggle: */
  539.     ObjScrTglWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  540.                       SubTransWidth, SubTransHeight);
  541.  
  542.     /* PERSPECTIVE/ORTHOGRPHIC toggle: */
  543.     PersOrthoTglWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  544.                          SubTransWidth, SubTransHeight);
  545.     PersOrthoZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  546.                          SubTransWidth, SubTransHeight);
  547.  
  548.     /* ROTATE: */
  549.     RotateXWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  550.                     SubTransWidth, SubTransHeight);
  551.     RotateYWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  552.                     SubTransWidth, SubTransHeight);
  553.     RotateZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  554.                     SubTransWidth, SubTransHeight);
  555.     /* TRANSLATE: */
  556.     TranslateXWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  557.                        SubTransWidth, SubTransHeight);
  558.     TranslateYWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  559.                        SubTransWidth, SubTransHeight);
  560.     TranslateZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  561.                        SubTransWidth, SubTransHeight);
  562.     /* SCALE: */
  563.     ScaleWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  564.                       SubTransWidth, SubTransHeight);
  565.  
  566.     /* DEPTH CUE: */
  567.     DepthCueWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  568.                      SubTransWidth, SubTransHeight);
  569.  
  570.     if (LclFullTransMode) {
  571.     /* SAVE GIF: */
  572.     SaveGIFWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  573.                         SubTransWidth, SubTransHeight);
  574.  
  575.     /* SAVE PS: */
  576.     SavePSWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  577.                        SubTransWidth, SubTransHeight);
  578.  
  579.     /* SAVE MATRIX: */
  580.     SaveMatrixWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  581.                            SubTransWidth, SubTransHeight);
  582.     }
  583.  
  584.     /* RESET MATRIX: */
  585.     ResetMatrixWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  586.                         SubTransWidth, SubTransHeight);
  587.  
  588.     /* QUIT: */
  589.     QuitWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY,
  590.                      SubTransWidth, SubTransHeight);
  591.  
  592.     XSelectInput(XDisplay, TransformWndw, ExposureMask);
  593.  
  594.     ObjectSpaceState = GlblTransformMode == TRANS_OBJECT;
  595.     PerspectiveState = GlblViewMode == VIEW_PERSPECTIVE;
  596.     DepthCueState = GlblDepthCue;
  597. }
  598.  
  599. /*****************************************************************************
  600. * Redraw a transformation window (after exposure or resize events).         *
  601. *****************************************************************************/
  602. static void RedrawTransformWindow(void)
  603. {
  604.     int SubTransPosX, SubTransPosY,
  605.         SizeChanged = FALSE;
  606.     unsigned long SubTransWidth, SubTransHeight;
  607.     long ValueMask;
  608.     XSizeHints Hints;
  609.     XWindowAttributes TransWindowAttr;
  610.     XSetWindowAttributes SetWinAttr;
  611.  
  612.     XClearWindow(XDisplay, TransformWndw);
  613.  
  614.     /* Get the window attributes, and see if it is the same size or not. */
  615.     XGetWindowAttributes(XDisplay, TransformWndw, &TransWindowAttr);
  616.     if (TransWindowAttr.width != TransWidth ||
  617.     TransWindowAttr.height != TransHeight)
  618.     {
  619.     SizeChanged = TRUE;
  620.     TransWidth = TransWindowAttr.width;
  621.     TransHeight = TransWindowAttr.height;
  622.     }
  623.  
  624.     /* Now lets update the sub windows inside: */
  625.     SubTransPosX = MIN(TransWidth / 10, 20);
  626.     SubTransPosY =  TransHeight / (LclFullTransMode ? 30 : 25);
  627.     SubTransWidth = TransWidth - SubTransPosX * 2;
  628.     SubTransHeight = TransHeight / (LclFullTransMode ? 30 : 25);
  629.  
  630.     /* OBJECT/SCREEN space toggle: */
  631.     RedrawTransformSubWindow(ObjScrTglWndw, SubTransPosX, SubTransPosY,
  632.                  SubTransWidth, SubTransHeight, FALSE,
  633.                  GlblTransformMode == TRANS_OBJECT ?
  634.                  "Object" : "Screen");
  635.     SubTransPosY += SubTransHeight * 2;
  636.  
  637.     /* PERSPECTIVE/ORTHOGRAPHIC toggle: */
  638.     RedrawTransformSubWindow(PersOrthoTglWndw, SubTransPosX, SubTransPosY,
  639.                  SubTransWidth, SubTransHeight, FALSE,
  640.                  GlblViewMode == VIEW_ORTHOGRAPHIC ?
  641.                  "Orthographic" : "Perspective");
  642.     SubTransPosY += SubTransHeight;
  643.     RedrawTransformSubWindow(PersOrthoZWndw, SubTransPosX, SubTransPosY,
  644.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  645.     SubTransPosY += SubTransHeight;
  646.     DrawText(TransformWndw, "Z", SubTransPosX / 2,
  647.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  648.     SubTransPosY += SubTransHeight;
  649.  
  650.     /* ROTATE: */
  651.     DrawText(TransformWndw, "Rotate", TransWidth / 2, SubTransPosY,
  652.          TransTextPixel);
  653.     SubTransPosY += SubTransHeight / 2;
  654.     RedrawTransformSubWindow(RotateXWndw, SubTransPosX, SubTransPosY,
  655.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  656.     SubTransPosY += SubTransHeight;
  657.     DrawText(TransformWndw, "X", SubTransPosX / 2,
  658.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  659.     RedrawTransformSubWindow(RotateYWndw, SubTransPosX, SubTransPosY,
  660.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  661.     SubTransPosY += SubTransHeight;
  662.     DrawText(TransformWndw, "Y", SubTransPosX / 2,
  663.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  664.     RedrawTransformSubWindow(RotateZWndw, SubTransPosX, SubTransPosY,
  665.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  666.     SubTransPosY += SubTransHeight;
  667.     DrawText(TransformWndw, "Z", SubTransPosX / 2,
  668.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  669.  
  670.     /* TRANSLATE: */
  671.     SubTransPosY += SubTransHeight;
  672.     DrawText(TransformWndw, "Translate", TransWidth / 2, SubTransPosY,
  673.          TransTextPixel);
  674.     SubTransPosY += SubTransHeight / 2;
  675.     RedrawTransformSubWindow(TranslateXWndw, SubTransPosX, SubTransPosY,
  676.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  677.     SubTransPosY += SubTransHeight;
  678.     DrawText(TransformWndw, "X", SubTransPosX / 2,
  679.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  680.     RedrawTransformSubWindow(TranslateYWndw, SubTransPosX, SubTransPosY,
  681.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  682.     SubTransPosY += SubTransHeight;
  683.     DrawText(TransformWndw, "Y", SubTransPosX / 2,
  684.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  685.     RedrawTransformSubWindow(TranslateZWndw, SubTransPosX, SubTransPosY,
  686.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  687.     SubTransPosY += SubTransHeight;
  688.     DrawText(TransformWndw, "Z", SubTransPosX / 2,
  689.          SubTransPosY - SubTransHeight / 4, TransTextPixel);
  690.  
  691.     /* SCALE: */
  692.     SubTransPosY += SubTransHeight;
  693.     DrawText(TransformWndw, "Scale", TransWidth / 2, SubTransPosY,
  694.          TransTextPixel);
  695.     SubTransPosY += SubTransHeight / 2;
  696.     RedrawTransformSubWindow(ScaleWndw, SubTransPosX, SubTransPosY,
  697.                  SubTransWidth, SubTransHeight, TRUE, NULL);
  698.  
  699.     /* DEPTH CUE: */
  700.     SubTransPosY += SubTransHeight * 2;
  701.     RedrawTransformSubWindow(DepthCueWndw, SubTransPosX, SubTransPosY,
  702.                  SubTransWidth, SubTransHeight, FALSE,
  703.                  GlblDepthCue ? "Depth Cue" : "No Depth Cue");
  704.  
  705.     if (LclFullTransMode) {
  706.     /* SAVE GIF: */
  707.     SubTransPosY += SubTransHeight * 2;
  708.     RedrawTransformSubWindow(SaveGIFWndw, SubTransPosX, SubTransPosY,
  709.                  SubTransWidth, SubTransHeight, FALSE,
  710.                  "Save GIF");
  711.  
  712.     /* SAVE PS: */
  713.     SubTransPosY += SubTransHeight * 2;
  714.     RedrawTransformSubWindow(SavePSWndw, SubTransPosX, SubTransPosY,
  715.                  SubTransWidth, SubTransHeight, FALSE,
  716.                  "Save PS");
  717.  
  718.     /* SAVE MATRIX: */
  719.     SubTransPosY += SubTransHeight * 2;
  720.     RedrawTransformSubWindow(SaveMatrixWndw, SubTransPosX, SubTransPosY,
  721.                  SubTransWidth, SubTransHeight, FALSE,
  722.                  "Save Matrix");
  723.     }
  724.  
  725.     /* RESET MATRIX: */
  726.     SubTransPosY += SubTransHeight * 2;
  727.     RedrawTransformSubWindow(ResetMatrixWndw, SubTransPosX, SubTransPosY,
  728.                  SubTransWidth, SubTransHeight, FALSE,
  729.                  "Reset Matrix");
  730.  
  731.     /* QUIT: */
  732.     SubTransPosY += SubTransHeight * 3;
  733.     RedrawTransformSubWindow(QuitWndw, SubTransPosX, SubTransPosY,
  734.                  SubTransWidth, SubTransHeight, FALSE, "Quit" );
  735.  
  736.     /* Save half of the window width so we can refer to the zero point on X */
  737.     /* axes, which is the vertical line in the middle of the window:        */
  738.     SubWindowWidthState2 = SubTransWidth / 2;
  739.     SubWindowHeightState2 = SubTransHeight / 2;
  740.  
  741.     GGGraphicFlush();
  742. }
  743.  
  744. /*****************************************************************************
  745. * Set up a transformation sub window.                         *
  746. *****************************************************************************/
  747. static Window SetTransformSubWindow(int SubTransPosX, int SubTransPosY,
  748.             unsigned int SubTransWidth, unsigned int SubTransHeight)
  749. {
  750.     long ValueMask;
  751.     XSetWindowAttributes SetWinAttr;
  752.     Window Win;
  753.  
  754.     SetWinAttr.background_pixel = TransSubWinBackPixel;
  755.     SetWinAttr.border_pixel = TransSubWinBorderPixel;
  756.     SetWinAttr.bit_gravity = SetWinAttr.win_gravity = CenterGravity;
  757.     ValueMask = CWBackPixel | CWBorderPixel | CWBitGravity | CWWinGravity;
  758.  
  759.     Win = XCreateWindow(XDisplay, TransformWndw,
  760.             SubTransPosX, SubTransPosY,
  761.             SubTransWidth, SubTransHeight,
  762.             1, 0, CopyFromParent, CopyFromParent,
  763.             ValueMask, &SetWinAttr);
  764.  
  765.     XSelectInput(XDisplay, Win, ButtonPressMask | Button1MotionMask);
  766.  
  767.     XMapWindow(XDisplay, Win);
  768.  
  769.     return Win;
  770. }
  771.  
  772. /*****************************************************************************
  773. * Redraw a transformation sub window.                         *
  774. *****************************************************************************/
  775. static void RedrawTransformSubWindow(Window Win,
  776.     int SubTransPosX, int SubTransPosY,
  777.     unsigned int SubTransWidth, unsigned int SubTransHeight,
  778.     int DrawMiddleVertLine, char *DrawString)
  779. {
  780.     XGCValues values;
  781.  
  782.     XMoveResizeWindow(XDisplay, Win, SubTransPosX, SubTransPosY,
  783.                                        SubTransWidth, SubTransHeight);
  784.     if (DrawMiddleVertLine) {
  785.     values.foreground = TransSubWinBorderPixel;
  786.     XChangeGC(XDisplay, XTransGraphContext, GCForeground, &values);
  787.  
  788.     XDrawLine(XDisplay, Win, XTransGraphContext,
  789.           SubTransWidth / 2, 0, SubTransWidth / 2, SubTransHeight);
  790.     }
  791.     if (DrawString != NULL) {
  792.     DrawText(Win, DrawString, SubTransWidth / 2, SubTransHeight / 2,
  793.          TransTextPixel);
  794.     }
  795. }
  796.  
  797. /*****************************************************************************
  798. * Set up a view window.                                 *
  799. *****************************************************************************/
  800. static void SetViewWindow(int argc, char **argv)
  801. {
  802.     long ValueMask;
  803.     XSizeHints Hints;
  804.     XSetWindowAttributes SetWinAttr;
  805.  
  806.     SetWinAttr.background_pixel = ViewBackGroundPixel;
  807.     SetWinAttr.border_pixel = ViewBorderPixel;
  808.     ValueMask = CWBackPixel | CWBorderPixel;
  809.  
  810.     Hints.flags = PMinSize | PMaxSize;
  811.     Hints.x = Hints.y = 1;
  812.     Hints.min_width = 50;
  813.     Hints.max_width = 1000;
  814.     Hints.min_height = 50;
  815.     Hints.max_height = 1000;
  816.     if (ViewHasSize) {
  817.     Hints.flags |= PSize;
  818.     if (ViewWidth < Hints.min_width) ViewWidth = Hints.min_width;
  819.     if (ViewWidth > Hints.max_width) ViewWidth = Hints.max_width;
  820.     if (ViewHeight < Hints.min_height) ViewHeight = Hints.min_height;
  821.     if (ViewHeight > Hints.max_height) ViewHeight = Hints.max_height;
  822.     Hints.width = ViewWidth;
  823.     Hints.height = ViewHeight;
  824.     }
  825.     else {
  826.     Hints.flags |= PSize;
  827.     Hints.width = ViewWidth = DEFAULT_VIEW_WIDTH;
  828.     Hints.height = ViewHeight = DEFAULT_VIEW_HEIGHT;
  829.     }
  830.     if (ViewHasPos) {
  831.     Hints.flags |= USPosition;
  832.     Hints.x = ViewPosX;
  833.     Hints.y = ViewPosY;
  834.     }
  835.  
  836.     ViewWndw = XCreateWindow(XDisplay, XRoot,
  837.                  ViewPosX, ViewPosY,
  838.                  ViewWidth, ViewHeight,
  839.                  1, 0, CopyFromParent, CopyFromParent,
  840.                  ValueMask, &SetWinAttr);
  841.  
  842.     XSetStandardProperties(XDisplay, ViewWndw,
  843.                PROGRAM_NAME, PROGRAM_NAME, None,
  844.                argv, argc,
  845.                &Hints);
  846.  
  847.     /* Set our own cursor: */
  848.     XCursor = XCreateFontCursor(XDisplay, XC_iron_cross);
  849.     XDefineCursor(XDisplay, ViewWndw, XCursor);
  850.     if (ViewCursorColor != NULL)
  851.     XRecolorCursor(XDisplay, XCursor, ViewCursorColor, &BlackColor);
  852.  
  853.     XSelectInput(XDisplay, ViewWndw, ExposureMask | ButtonPressMask);
  854.     
  855.     XMapWindow(XDisplay, ViewWndw);
  856. }
  857.  
  858. /*****************************************************************************
  859. * Return View window ID and the address of the display it is in.         *
  860. *****************************************************************************/
  861. long GGGetViewWindowID(long *XDisplayAddr, long *XColorMapID)
  862. {
  863.     *XDisplayAddr = (long) XDisplay;
  864.     *XColorMapID = (long) XColorMap;
  865.  
  866.     return (long) ViewWndw;
  867. }
  868.  
  869. /******************************************************************************
  870. * Returns status of abort key if pressed, and reset it.                  *
  871. ******************************************************************************/
  872. int GGIsAbortKeyPressed(void)
  873. {
  874.     int RetVal = AbortKeyPressed;
  875.  
  876.     AbortKeyPressed = FALSE;
  877.  
  878.     return RetVal;
  879. }
  880.  
  881. /******************************************************************************
  882. * Flush output of graphic command.                          *
  883. ******************************************************************************/
  884. void GGGraphicFlush(void)
  885. {
  886.     XFlush(XDisplay);
  887. }
  888.  
  889. /******************************************************************************
  890. * Handle X events                                  *
  891. ******************************************************************************/
  892. GraphicEventType GGGetGraphicEvent(RealType *ChangeFactor)
  893. {
  894.     static int LastX;
  895.     int Dx;
  896.     XEvent Event;
  897.     XWindowAttributes WinAttr;
  898.  
  899.     XMapWindow(XDisplay, TransformWndw);
  900.  
  901.     while (TRUE) {
  902.     XNextEvent(XDisplay, &Event);
  903.     switch (Event.type) {
  904.         case Expose:
  905.             /* Get rid of all Expose events in the queue. */
  906.             while (XCheckWindowEvent(XDisplay, Event.xbutton.window,
  907.                           ExposureMask, &Event));
  908.             if (Event.xbutton.window == TransformWndw)
  909.             RedrawTransformWindow();
  910.         else if (Event.xbutton.window == ViewWndw) {
  911.             XGetWindowAttributes(XDisplay, ViewWndw, &WinAttr);
  912.             ViewWidth = WinAttr.width;
  913.             ViewHeight = WinAttr.height;
  914.             UpdateInteractHandleInput();
  915.         }
  916.         break;
  917.         case ButtonPress:
  918.         LastX = Event.xbutton.x;
  919.         *ChangeFactor = ((RealType) (LastX - SubWindowWidthState2)) /
  920.                             SubWindowWidthState2;
  921.         if (Event.xbutton.button == 3) {
  922.             AbortKeyPressed = TRUE;
  923.             break;
  924.         }
  925.  
  926.         if (Event.xbutton.window == ObjScrTglWndw) {
  927.             XClearWindow(XDisplay, ObjScrTglWndw);
  928.             GlblTransformMode = GlblTransformMode == TRANS_OBJECT ?
  929.                                  TRANS_SCREEN :
  930.                                  TRANS_OBJECT;
  931.             DrawText(ObjScrTglWndw,
  932.                  GlblTransformMode == TRANS_OBJECT ? "Object" :
  933.                                  "Screen",
  934.                  SubWindowWidthState2, SubWindowHeightState2,
  935.                  TransTextPixel);
  936.             return EVENT_SCR_OBJ_TGL;
  937.         }
  938.         else if (Event.xbutton.window == PersOrthoTglWndw) {
  939.             XClearWindow(XDisplay, PersOrthoTglWndw);
  940.             GlblViewMode = GlblViewMode == VIEW_PERSPECTIVE ?
  941.                                VIEW_ORTHOGRAPHIC :
  942.                                VIEW_PERSPECTIVE;
  943.             DrawText(PersOrthoTglWndw,
  944.                  GlblViewMode == VIEW_PERSPECTIVE ? "Perspective" :
  945.                                                     "Orthographic",
  946.                  SubWindowWidthState2, SubWindowHeightState2,
  947.                  TransTextPixel);
  948.             return EVENT_PERS_ORTHO_TGL;
  949.         }
  950.         else if (Event.xbutton.window == PersOrthoZWndw) {
  951.             return EVENT_PERS_ORTHO_Z;
  952.         }
  953.         else if (Event.xbutton.window == RotateXWndw) {
  954.             return EVENT_ROTATE_X;
  955.         }
  956.         else if (Event.xbutton.window == RotateYWndw) {
  957.             return EVENT_ROTATE_Y;
  958.         }
  959.         else if (Event.xbutton.window == RotateZWndw) {
  960.             return EVENT_ROTATE_Z;
  961.         }
  962.         else if (Event.xbutton.window == TranslateXWndw) {
  963.             return EVENT_TRANSLATE_X;
  964.         }
  965.         else if (Event.xbutton.window == TranslateYWndw) {
  966.             return EVENT_TRANSLATE_Y;
  967.         }
  968.         else if (Event.xbutton.window == TranslateZWndw) {
  969.             return EVENT_TRANSLATE_Z;
  970.         }
  971.         else if (Event.xbutton.window == ScaleWndw) {
  972.             return EVENT_SCALE;
  973.         }
  974.         else if (Event.xbutton.window == DepthCueWndw) {
  975.             XClearWindow(XDisplay, DepthCueWndw);
  976.             GlblDepthCue = !GlblDepthCue;
  977.             DrawText(DepthCueWndw,
  978.                  GlblDepthCue ? "Depth Cue" : "No Depth Cue",
  979.                  SubWindowWidthState2, SubWindowHeightState2,
  980.                  TransTextPixel);
  981.             return EVENT_DEPTH_CUE;
  982.         }
  983.         else if (LclFullTransMode &&
  984.              Event.xbutton.window == SaveMatrixWndw) {
  985.             return EVENT_SAVE_MATRIX;
  986.         }
  987.         else if (LclFullTransMode &&
  988.              Event.xbutton.window == SaveGIFWndw) {
  989.             return EVENT_SAVE_GIF;
  990.         }
  991.         else if (LclFullTransMode &&
  992.              Event.xbutton.window == SavePSWndw) {
  993.             return EVENT_SAVE_PS;
  994.         }
  995.         else if (Event.xbutton.window == ResetMatrixWndw) {
  996.             return EVENT_RESET_MATRIX;
  997.         }
  998.         else if (Event.xbutton.window == QuitWndw) {
  999.             if (!PopTransWndwAlways)
  1000.             XUnmapWindow(XDisplay, TransformWndw);
  1001.             GGGraphicFlush();
  1002.             return EVENT_QUIT;
  1003.         }
  1004.         break;
  1005.         case MotionNotify:
  1006.         /* We may get events of movement in Y which are ignored. */
  1007.         if (Event.xbutton.x - LastX == 0) break;
  1008.  
  1009.         *ChangeFactor = ((RealType) (Event.xbutton.x - LastX)) /
  1010.                             SubWindowWidthState2;
  1011.         LastX = Event.xbutton.x;
  1012.  
  1013.         if (Event.xbutton.window == PersOrthoZWndw) {
  1014.             return EVENT_PERS_ORTHO_Z;
  1015.         }
  1016.         else if (Event.xbutton.window == RotateXWndw) {
  1017.             return EVENT_ROTATE_X;
  1018.         }
  1019.         else if (Event.xbutton.window == RotateYWndw) {
  1020.             return EVENT_ROTATE_Y;
  1021.         }
  1022.         else if (Event.xbutton.window == RotateZWndw) {
  1023.             return EVENT_ROTATE_Z;
  1024.         }
  1025.         else if (Event.xbutton.window == TranslateXWndw) {
  1026.             return EVENT_TRANSLATE_X;
  1027.         }
  1028.         else if (Event.xbutton.window == TranslateYWndw) {
  1029.             return EVENT_TRANSLATE_Y;
  1030.         }
  1031.         else if (Event.xbutton.window == TranslateZWndw) {
  1032.             return EVENT_TRANSLATE_Z;
  1033.         }
  1034.         else if (Event.xbutton.window == ScaleWndw) {
  1035.             return EVENT_SCALE;
  1036.         }
  1037.         break;
  1038.         default:
  1039.         fprintf(stderr, "undefined event type %d.\n", Event.type);
  1040.     }
  1041.     }
  1042. }
  1043.  
  1044. /******************************************************************************
  1045. * Draw text centered at the given position.                      *
  1046. ******************************************************************************/
  1047. static void DrawText(Window Win, char *Str, int PosX, int PosY,
  1048.              unsigned long Color)
  1049. {
  1050.     int Len = strlen(Str),
  1051.         Width = XTextWidth(XLoadedFont, Str, Len);
  1052.     XGCValues values;
  1053.  
  1054.     values.foreground = Color;
  1055.     XChangeGC(XDisplay, XTransGraphContext, GCForeground, &values);
  1056.  
  1057.     XDrawString(XDisplay, Win, XTransGraphContext, PosX - Width / 2,
  1058.         PosY + XFontYOffsetToCenter, Str, Len);
  1059. }
  1060.